package com.pig4cloud.pig.ads.gdt.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.pig4cloud.pig.ads.gdt.service.GdtAccesstokenService;
import com.pig4cloud.pig.ads.gdt.service.GdtBrandImageService;
import com.pig4cloud.pig.ads.pig.mapper.gdt.GdtBrandImageMapper;
import com.pig4cloud.pig.ads.service.AdvService;
import com.pig4cloud.pig.ads.utils.DateUtils;
import com.pig4cloud.pig.ads.utils.MultipartFileToFile;
import com.pig4cloud.pig.ads.utils.OEHttpUtils;
import com.pig4cloud.pig.api.entity.GdtBrandImage;
import com.pig4cloud.pig.api.entity.ResponseBean;
import com.pig4cloud.pig.api.util.MapUtils;
import com.pig4cloud.pig.api.util.UploadUtils;
import com.pig4cloud.pig.api.vo.GdtBrandImageVo;
import com.pig4cloud.pig.common.core.constant.enums.PlatformTypeEnum;
import com.pig4cloud.pig.common.core.util.R;
import com.pig4cloud.pig.common.security.util.SecurityUtils;
import lombok.RequiredArgsConstructor;
import lombok.extern.log4j.Log4j2;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.http.entity.ContentType;
import org.apache.http.entity.mime.MultipartEntityBuilder;
import org.apache.http.entity.mime.content.FileBody;
import org.apache.http.protocol.HTTP;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.File;
import java.util.*;

/**
 * @description:
 * @author: nml
 * @time: 2020/12/4 15:19
 **/
@Log4j2
@Service
@RequiredArgsConstructor
public class GdtBrandImageServiceImpl extends ServiceImpl<GdtBrandImageMapper, GdtBrandImage> implements GdtBrandImageService {

	private final GdtBrandImageMapper gdtBrandImageMapper;

	private final GdtAccesstokenService gdtAccesstokenService;

	private final AdvService advService;

	@Value("${brand_image_download_url}")
	private String downloadUrl;
	//下载地址
	@Value("${brand_image_upload_path}")
	private String uploadPath;
	//限制大小
	@Value("${brand_image_size}")
	private String imgSize;
	/**
	 * 广点通接口地址前缀
	 */
	@Value(value = "${gdt_url}")
	private String gdtUrl;

	/**
	 * 创建品牌形象接口地址
	 */
	@Value(value = "${gdt_brand_add_url}")
	private String gdtBrandAddUrl;


	//1、先上传文件，存储到本地服务器
	//2、将该file推送给当前登录账号下的 所有广告账户id。并接收返回值
	//3、将本地上传的字段信息 + 推送的返回字段信息整合，一起入库
	@Override
	public R pushBrandImage(String[] advertiserIds,String[] names, MultipartFile[] imgFiles) {
		if (Objects.isNull(imgFiles) || imgFiles.length <= 0) {
			return R.failed("请选择品牌形象图片");
		}
		if (Objects.isNull(names) || names.length <= 0) {
			return R.failed("请输入品牌形象图片名称");
		}
		//!!!获取当前账户下的广告账户集合
		Integer userId = SecurityUtils.getUser().getId();
		List<String> authAdvList = advService.getOwnerAdv(userId, PlatformTypeEnum.GDT.getValue());

		if (authAdvList.isEmpty()){
			return R.failed("当前账户无授权的广告账户id！");
		}

		//前端参数：广告账户ids
		if (Objects.isNull(advertiserIds) || advertiserIds.length <= 0){
			return R.failed("请选择广告账户id");
		}
		List<String> advertiserIdsList = Arrays.asList(advertiserIds);
		//存放推送失败的广告账号信息
		List<String> adverIdList = Lists.newArrayList();

		//接收上传的图片文件
		String ymPath = DateUtils.dateToString(new Date(), DateUtils.YYYYMM) + "/";
		String upPath = uploadPath + ymPath;
		String downUrl = downloadUrl + ymPath;
		//遍历多张图片
		for (int i = 0; i < imgFiles.length; i++) {
			try {
				//处理上传的文件
				MultipartFile mFile = imgFiles[i];
				//查看视频是否已经上传
				String md5 = DigestUtils.md5Hex(mFile.getInputStream());
				//当前文件的图片名称
				String imgName = names[i];
				//判断当前广告账户下，是否存在相同md5和图片name的记录。
				for (int j = 0; j < advertiserIdsList.size(); j++) {
					String accountId = advertiserIdsList.get(j);
					GdtBrandImage gdtImage = gdtBrandImageMapper.selectOne(Wrappers.<GdtBrandImage>query().lambda().eq(GdtBrandImage::getMd5, md5).eq(GdtBrandImage::getName, imgName).eq(GdtBrandImage::getAccountId, accountId).last("LIMIT 1"));
					String msg = "广告账户id：" + accountId + "下,存在该图片内容及图片名称：" + imgName + "，请修改图片名称!";
					if (null != gdtImage) {
						return R.failed(msg);
					}
				}

				//上传图片到本地服务器
				long picSize = 2 * 1024 * 1024;
				if (StringUtils.isNotBlank(imgSize) && !"null".equals(imgSize)) {
					picSize = Long.parseLong(imgSize);
				}
				//上传图片到本地服务器
				Map<String, Object> resultMap = UploadUtils.imageUpload(upPath, mFile, picSize);
				Integer code = (Integer) resultMap.get("code");
				//如果图片上传成功执行推送操作，推送成功后将所有信息入库操作
				if (0 == code) {
					GdtBrandImage brandImage = new GdtBrandImage();
					//获取图片信息
					//前端输入的图片名称
					brandImage.setName(imgName);
					String filename = (String) resultMap.get("filename");
					//图片文件名
					brandImage.setPicFilename(filename);
					//图片访问url
					brandImage.setPicUrl(downUrl + filename);
					//获取图片宽高
					Double width = (Double) resultMap.get("width");
					int width1 = width.intValue();
					Double height = (Double) resultMap.get("height");
					int height1 = height.intValue();
					//图片宽
					brandImage.setWidth(String.valueOf(width1));
					//图片高
					brandImage.setHeight(String.valueOf(height1));
					//图片格式
					brandImage.setFormat((String) resultMap.get("format"));
					brandImage.setMd5(md5);
					brandImage.setRealPath((String) resultMap.get("realPath"));
					//图片大小
					brandImage.setPicSize(String.valueOf(mFile.getSize()));
					//图片状态
					brandImage.setIsdelete(0);
					//上传人createUser
					brandImage.setCreateuser(String.valueOf(userId));
					Date nowDate = new Date();
					brandImage.setCreatetime(nowDate);
					brandImage.setUpdatetime(nowDate);
					//文件类型转换
					File file = MultipartFileToFile.multipartFileToFile(mFile);
					//调用推送方法
					adverIdList = pushPicGdt(brandImage, file, advertiserIdsList);
					//判断当前图片是否全部推送成功：若未全部成功，返回前端推送失败信息，并中断其他图片同步。
					if (!adverIdList.isEmpty()) {
						String msg = "图片：" + imgName + "推送失败的广告账户id:" + adverIdList.toString();
						return R.failed(adverIdList, msg);
					}
				} else {
					//当前图片上传失败
					return R.failed("图片" + imgName + "上传本地服务器失败");
				}
			} catch (Exception e) {
				e.printStackTrace();
				log.error("文件上传失败：{}", e.getMessage());
				return R.failed("文件上传失败");
			}
		}
		//多张图片文件均上传成功，且推送给当前账户下多个广告账户成功。
		return R.ok("上传推送成功");
	}

	//同步品牌形象到广点通方法
	@Override
	public List<String> pushPicGdt(GdtBrandImage gbi, File imgFile, List<String> authAdvList) {
		//广告账户列表authAdvList
		String msg = "";
		List<String> advertiserIdList = Lists.newArrayList();
		//遍历广告账户,推送品牌形象
		for (int i = 0; i < authAdvList.size(); i++) {
			String advertiserId = authAdvList.get(i);
			//公共方法获取accessToken
			Map<String, String> map = gdtAccesstokenService.fetchAccesstoken(advertiserId);
			//定义广点通接口url
			String url = gdtUrl + gdtBrandAddUrl + "?" + MapUtils.queryString(map);
			// 文件参数
			FileBody file = new FileBody(imgFile);
			MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create()
					.addPart("brand_image_file", file);
			// 其他参数
			//entityBuilder.setContentType(ContentType.APPLICATION_JSON);//报错，没有解决中文乱码的问题
			entityBuilder.addTextBody("account_id", advertiserId);
			ContentType contentType = ContentType.create(HTTP.PLAIN_TEXT_TYPE, HTTP.UTF_8);
			entityBuilder.addTextBody("name", gbi.getName(), contentType);
			//调第三方平台（广点通）接口
			String resultStr = OEHttpUtils.doFilePost(url, entityBuilder);
			ResponseBean resBean = JSON.parseObject(resultStr, ResponseBean.class);
			//调用成功,信息入库
			if (resBean != null && "0".equals(resBean.getCode())) {
				Map<String, Object> picData = resBean.getData();
				//广告账户
				gbi.setAccountId(advertiserId);
				//图片类型（头条要求的）固定先
				gbi.setImageId(String.valueOf(picData.get("image_id")));
				gbi.setImageUrl(String.valueOf(picData.get("image_url")));
				gbi.setCreatedTime(String.valueOf(picData.get("created_time")));
				//保存推送成功的品牌形象信息
				try {
					this.save(gbi);
				} catch (Exception e) {
					e.printStackTrace();
				}
				log.info(">>>广点通图片ID:{} >>>预览地址:{}", String.valueOf(picData.get("image_id")), String.valueOf(picData.get("image_url")));
				log.info(">>>图片ID:{}，上传广点通账户:{}，成功", String.valueOf(picData.get("image_id")), advertiserId);
			} else {
				msg = ">>>图片ID：" + "" + "，上传广点通账户：" + advertiserId + "，失败，原因：" + resBean.getMessage();
				log.info("推送失败信息：{}", msg);
				advertiserIdList.add(advertiserId);
			}
		}
		//推送失败的广告账户集合
		return advertiserIdList;
	}


	@Override
	public List<String> pushPicGdtCopy(GdtBrandImage gbi, File imgFile, List<String> authAdvList) {
		//广告账户列表authAdvList
		String msg = "";
		List<String> imageIdList = Lists.newArrayList();
		//遍历广告账户,推送品牌形象
		for (int i = 0; i < authAdvList.size(); i++) {
			String advertiserId = authAdvList.get(i);
			//公共方法获取accessToken
			Map<String, String> map = gdtAccesstokenService.fetchAccesstoken(advertiserId);
			//定义广点通接口url
			String url = gdtUrl + gdtBrandAddUrl + "?" + MapUtils.queryString(map);
			// 文件参数
			FileBody file = new FileBody(imgFile);
			MultipartEntityBuilder entityBuilder = MultipartEntityBuilder.create()
					.addPart("brand_image_file", file);
			// 其他参数
			//entityBuilder.setContentType(ContentType.APPLICATION_JSON);//报错，没有解决中文乱码的问题
			entityBuilder.addTextBody("account_id", advertiserId);
			ContentType contentType = ContentType.create(HTTP.PLAIN_TEXT_TYPE, HTTP.UTF_8);
			entityBuilder.addTextBody("name", gbi.getName(), contentType);
			//调第三方平台（广点通）接口
			String resultStr = OEHttpUtils.doFilePost(url, entityBuilder);
			ResponseBean resBean = JSON.parseObject(resultStr, ResponseBean.class);
			//调用成功,信息入库
			if (resBean != null && "0".equals(resBean.getCode())) {
				Map<String, Object> picData = resBean.getData();
				//广告账户
				gbi.setAccountId(advertiserId);
				//图片类型（头条要求的）固定先
				gbi.setImageId(String.valueOf(picData.get("image_id")));
				gbi.setImageUrl(String.valueOf(picData.get("image_url")));
				gbi.setCreatedTime(String.valueOf(picData.get("created_time")));
				//保存推送成功的品牌形象信息
				try {
					this.save(gbi);
				} catch (Exception e) {
					e.printStackTrace();
				}
				log.info(">>>广点通图片ID:{} >>>预览地址:{}", String.valueOf(picData.get("image_id")), String.valueOf(picData.get("image_url")));
				log.info(">>>图片ID:{}，上传广点通账户:{}，成功", String.valueOf(picData.get("image_id")), advertiserId);
				imageIdList.add(String.valueOf(picData.get("image_id")));
			} else {
				msg = ">>>图片ID：" + "" + "，上传广点通账户：" + advertiserId + "，失败，原因：" + resBean.getMessage();
				log.info("推送失败信息：{}", msg);

			}
		}
		//推送成功的image_id集合
		return imageIdList;
	}


	//分页列表
	@Override
	public R findPage(GdtBrandImageVo req) {
		//设置分页条件
		Page page = new Page();
		page.setSize(req.getSize());
		page.setCurrent(req.getCurrent());
		QueryWrapper<GdtBrandImage> queryWrapper = new QueryWrapper<>();
		IPage<GdtBrandImage> data = null;
		//设置where条件
		//!!!获取当前账户下的广告账户集合
		Integer userId = SecurityUtils.getUser().getId();
		List<String> authAdvList = advService.getOwnerAdv(userId, PlatformTypeEnum.GDT.getValue());
		//如果没有绑定广告账户则什么都看不到！
		if (authAdvList.isEmpty()){
			return R.ok(data,"当前账户没有绑定广告账户id");
		}

		//过滤：广告账户ids
		//前端传了广告账户参数
		String advertiserIds = req.getAdvertiserIds();
		if (StringUtils.isNotBlank(advertiserIds)){
			String[] ids = advertiserIds.split(",");
			queryWrapper.in("account_id", ids);
		}else {//没有传广告账户参数，则查当前账户下
			queryWrapper.in("account_id", authAdvList);
		}


		//过滤：品牌形象名称
		if (StringUtils.isNotBlank(req.getName())){
			queryWrapper.like("name",req.getName());
		}
		queryWrapper.eq("width", "512");
		queryWrapper.eq("height", "512");
		queryWrapper.eq("isdelete", 0);
		//queryWrapper.orderByDesc("updatetime desc,id");
		queryWrapper.orderByDesc("updatetime");
		queryWrapper.orderByDesc("id");

		try {
			data = gdtBrandImageMapper.selectPage(page, queryWrapper);
		} catch (Exception e) {
			e.printStackTrace();
			log.error("findPage is error",e);
			return R.failed(data, e.getMessage());
		}
		return R.ok(data, "请求成功");
	}

}
